home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Freeware / Swf_Player / Lib / graphic24.cc < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  15.5 KB  |  649 lines

  1. ////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include "swf.h"
  24.  
  25. #include "graphic24.h"
  26.  
  27. extern unsigned char SQRT[];
  28.  
  29. #define FULL_AA
  30.  
  31. #define PRINT 0
  32.  
  33. typedef unsigned char TYPE;
  34. #define BPP 3
  35.  
  36. GraphicDevice24::GraphicDevice24(FlashDisplay *fd) : GraphicDevice(fd)
  37. {
  38. }
  39.  
  40. long
  41. GraphicDevice24::allocColor(Color color)
  42. {
  43.     return 0;
  44. }
  45.  
  46. void
  47. GraphicDevice24::clearCanvas()
  48. {
  49.     TYPE *point,*p;
  50.     long                 h, w,n;
  51.  
  52.     if (!bgInitialized) return;
  53.  
  54.     point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin*BPP;
  55.     w = clip_rect.xmax - clip_rect.xmin;
  56.     h = clip_rect.ymax - clip_rect.ymin;
  57.  
  58.     while (h--) {
  59.         p = point;
  60.         n = w;
  61.         while (n--) {
  62.             *p++ = backgroundColor.blue;
  63.             *p++ = backgroundColor.green;
  64.             *p++ = backgroundColor.red;
  65.         }
  66.  
  67.         point = (TYPE *)((char *)point + bpl);
  68.     }
  69.  
  70.     flashDisplay->flash_refresh = 1;
  71.     flashDisplay->clip_x = clip_rect.xmin;
  72.     flashDisplay->clip_y = clip_rect.ymin;
  73.     flashDisplay->clip_width  = clip_rect.xmax-clip_rect.xmin;
  74.     flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin;
  75. }
  76.  
  77. /* alpha = 0 : select c1, alpha = 255 select c2 */
  78. static inline void mix_alpha(TYPE *c1, Color c2, int alpha)
  79. {
  80.     *c1 = (((c2.blue- (*c1))*alpha + (*c1) * 256) >> 8);
  81.     c1++;
  82.     *c1 = (((c2.green- (*c1))*alpha + (*c1) * 256) >> 8);
  83.     c1++;
  84.     *c1 = (((c2.red- (*c1))*alpha + (*c1) * 256) >> 8);
  85. }
  86.  
  87. void
  88. GraphicDevice24::fillLineAA(FillStyleDef *f, long y, long start, long end)
  89. {
  90.     register long   n;
  91.     TYPE *line;
  92.     TYPE *point;
  93.     Color pixel;
  94.     unsigned int alpha, start_alpha,end_alpha;
  95.     
  96.     if (clip(y,start,end)) return;
  97.     
  98.     line = (TYPE *)(canvasBuffer + bpl*y);
  99.     
  100.     alpha = f->color.alpha;
  101.     pixel = f->color;
  102.     
  103.     if (alpha == ALPHA_OPAQUE) {
  104.  
  105.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  106.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  107.         
  108.         start >>= FRAC_BITS;
  109.         end >>= FRAC_BITS;
  110.         
  111.         point = &line[start*BPP];
  112.  
  113.         if (start == end) {
  114.             mix_alpha(point, pixel, start_alpha + end_alpha - 255);
  115.         } else {
  116.             n = end-start;
  117.             if (start_alpha < 255) {
  118.                 mix_alpha(point, pixel, start_alpha);
  119.                 point += BPP;
  120.                 n--;
  121.             }
  122.             while (n > 0) {
  123.                 *point++ = pixel.blue;
  124.                 *point++ = pixel.green;
  125.                 *point++ = pixel.red;
  126.                 n--;
  127.             }
  128.             if (end_alpha > 0) {
  129.                 mix_alpha(point, pixel, end_alpha);
  130.             }
  131.         }
  132.     } else {
  133.  
  134.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  135.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  136.  
  137.         start >>= FRAC_BITS;
  138.         end >>= FRAC_BITS;
  139.         
  140.         point = &line[start*BPP];
  141.         
  142.         if (start == end) {
  143.             mix_alpha(point, pixel, ((start_alpha + end_alpha - 255) * alpha) >> 8);
  144.         } else {
  145.             n = end-start;
  146.             if (start_alpha < 255) {
  147.                 mix_alpha(point, pixel, (start_alpha * alpha) >> 8);
  148.                 point+=BPP;
  149.                 n--;
  150.             }
  151.             while (n > 0) {
  152.                 mix_alpha(point, pixel, alpha);
  153.                 point+=BPP;
  154.                 n--;
  155.             }
  156.             if (end_alpha > 0) {
  157.                 mix_alpha(point, pixel, (end_alpha * alpha) >> 8);
  158.             }
  159.         }
  160.     }
  161. }
  162.  
  163. void
  164. GraphicDevice24::fillLine(FillStyleDef *f, long y, long start, long end)
  165. {
  166.     register long   n;
  167.         TYPE *line,*point;
  168.         Color pixel;
  169.         unsigned int alpha;
  170.  
  171.     if (clip(y,start,end)) return;
  172.  
  173.         start >>= FRAC_BITS;
  174.         end >>= FRAC_BITS;
  175.  
  176.     line = (TYPE *)(canvasBuffer + bpl*y);
  177.     point = &line[start*BPP];            
  178.     n = end-start;                
  179.         alpha = f->color.alpha;
  180.         pixel = f->color;
  181.         if (alpha == ALPHA_OPAQUE) {
  182.             while (n--) { 
  183.         *point++ = pixel.blue;
  184.         *point++ = pixel.green;
  185.         *point++ = pixel.red;
  186.             }
  187.         } else {
  188.             while (n--) { 
  189.         mix_alpha(point, pixel, alpha);
  190.         point+=BPP;            
  191.             }
  192.         }
  193. }
  194.  
  195. void
  196. GraphicDevice24::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
  197. {
  198.     int n;
  199.     long x1,y1,dx,dy;
  200.     Matrix *m = &f->bitmap_matrix;
  201.     Bitmap *b = f->bitmap;
  202.     unsigned char *pixels;
  203.     TYPE *p;
  204.     Color *cmap;
  205.     long pixbpl;
  206.     Color pixel;
  207.     int offset;
  208.     unsigned char *alpha_table;
  209.  
  210.     /* safety test) */
  211.     if (!b) return;
  212.  
  213.     if (clip(y,start,end)) return;
  214.     
  215.     start /= FRAC;
  216.     end /= FRAC;
  217.     n = end - start;
  218.     p = (TYPE *) (canvasBuffer + bpl*y + start*BPP);
  219.     
  220.     x1 = (long) (m->a * start + m->b * y + m->tx);
  221.     y1 = (long) (m->c * start + m->d * y + m->ty);
  222.     dx = (long) (m->a);
  223.     dy = (long) (m->c);
  224.     
  225.     pixels = b->pixels;
  226.     pixbpl = b->bpl;
  227.     cmap = f->cmap;
  228.  
  229.     if (b->alpha_buf == NULL) {
  230.         while (n) {
  231.             if (x1 >= 0 && y1 >= 0 && 
  232.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  233.                 
  234.                 pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]];
  235.                 *p++ = pixel.blue;
  236.                 *p++ = pixel.green;
  237.                 *p++ = pixel.red;
  238.             } else {
  239.                 p+=BPP;
  240.         }
  241.             x1 += dx;
  242.             y1 += dy;
  243.             n--;
  244.         }
  245.     } else if (f->alpha_table) {
  246.         alpha_table = f->alpha_table;
  247.         while (n) {
  248.             if (x1 >= 0 && y1 >= 0 && 
  249.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  250.                 
  251.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  252.                 mix_alpha(p, cmap[pixels[offset]], alpha_table[b->alpha_buf[offset]]);
  253.         }
  254.             p+=BPP;
  255.             x1 += dx;
  256.             y1 += dy;
  257.             n--;
  258.         }
  259.     } else {
  260.         while (n) {
  261.             if (x1 >= 0 && y1 >= 0 && 
  262.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  263.                 
  264.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  265.                 mix_alpha(p, cmap[pixels[offset]], b->alpha_buf[offset]);
  266.             }
  267.             p+=BPP;
  268.             x1 += dx;
  269.             y1 += dy;
  270.             n--;
  271.         }
  272.     }
  273. }
  274.  
  275. void
  276. GraphicDevice24::fillLineLG(Gradient *grad, long y, long start, long end)
  277. {
  278.     long dr,r,v,r2;
  279.     register long n;
  280.     TYPE *line;
  281.     TYPE *point;
  282.         Color *cp,*ramp;
  283.         Matrix *m = &grad->imat;
  284.         unsigned int start_alpha,end_alpha;
  285.  
  286.     if (clip(y,start,end)) return;
  287.  
  288.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  289.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  290.         
  291.     start /= FRAC;
  292.     end /= FRAC;
  293.  
  294.     n = end-start;
  295.  
  296.         r = (long) (m->a * start + m->b * y + m->tx);
  297.         dr = (long) (m->a);
  298.  
  299.         ramp = grad->ramp;
  300.  
  301.         line = (TYPE *)(canvasBuffer + bpl*y);
  302.     point = &line[start*BPP];
  303.  
  304.         r2 = r + n * dr;
  305.         if ( ((r | r2) & ~255) == 0 ) {
  306.             if (!grad->has_alpha) {
  307. #ifdef FULL_AA
  308.         if (start_alpha < 255) {
  309.                     v = r>>16;
  310.                     mix_alpha(point, ramp[v], start_alpha);
  311.                     point+=BPP;
  312.                     r += dr;
  313.             n--;
  314.         }
  315. #endif /* FULL_AA */
  316.                 while (n>0) {
  317.                     v = r>>16;
  318.                     *point++ = ramp[v].blue;
  319.                     *point++ = ramp[v].green;
  320.                     *point++ = ramp[v].red;
  321.                     r += dr;                
  322.             n--;
  323.                 }
  324. #ifdef FULL_AA
  325.         if (end_alpha > 0) {
  326.                     v = r>>16;
  327.                     mix_alpha(point, ramp[v], end_alpha);
  328.         }
  329. #endif /* FULL_AA */
  330.             } else {
  331.                 while (n--) {
  332.                     v = r>>16;
  333.                     cp = &ramp[v];
  334.                     mix_alpha(point, *cp, cp->alpha);
  335.                     point+=BPP;
  336.                     r += dr;
  337.                 }
  338.             }
  339.         } else {
  340.             if (!grad->has_alpha) {
  341. #ifdef FULL_AA
  342.         if (start_alpha < 255) {
  343.                     v = r>>16;
  344.                     if (v < 0) v = 0;
  345.                     else if (v > 255) v = 255;
  346.                     mix_alpha(point, ramp[v], start_alpha);
  347.                     point+=BPP;
  348.                     r += dr;
  349.             n--;
  350.         }
  351. #endif /* FULL_AA */
  352.                 while (n>0) {
  353.                     v = r>>16;
  354.                     if (v < 0) v = 0;
  355.                     else if (v > 255) v = 255;
  356.                     *point++ = ramp[v].blue;
  357.                     *point++ = ramp[v].green;
  358.                     *point++ = ramp[v].red;
  359.                     r += dr;                
  360.             n--;
  361.                 }
  362. #ifdef FULL_AA
  363.         if (end_alpha > 0) {
  364.                     v = r>>16;
  365.                     if (v < 0) v = 0;
  366.                     else if (v > 255) v = 255;
  367.                     mix_alpha(point, ramp[v], end_alpha);
  368.         }
  369. #endif /* FULL_AA */
  370.             } else {
  371.                 while (n--) {
  372.                     v = r>>16;
  373.                     if (v < 0) v = 0;
  374.                     else if (v > 255) v = 255;
  375.                     cp = &ramp[v];
  376.                     mix_alpha(point, *cp, cp->alpha);
  377.                     point+=BPP;
  378.                     r += dr;
  379.                 }
  380.             }
  381.         }
  382. }
  383.  
  384. void
  385. GraphicDevice24::fillLineRG(Gradient *grad, long y, long start, long end)
  386. {
  387.     long X,dx,r,Y,dy;
  388.     long dist2;
  389.     register long   n;
  390.         Color *cp,*ramp;
  391.     TYPE *line;                            
  392.     TYPE *point;                            
  393.         Matrix *m = &grad->imat;
  394.         unsigned int start_alpha,end_alpha;
  395.  
  396.     if (clip(y,start,end)) return;
  397.  
  398.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  399.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  400.         
  401.     start /= FRAC;
  402.     end /= FRAC;
  403.  
  404.     n = end-start;
  405.         
  406.         X = (long) (m->a * start + m->b * y + m->tx);
  407.         Y = (long) (m->c * start + m->d * y + m->ty);
  408.         dx = (long) (m->a);
  409.         dy = (long) (m->c);
  410.  
  411.         ramp = grad->ramp;
  412.                                     
  413.     line = (TYPE *)(canvasBuffer + bpl*y);
  414.     point = &line[start*BPP];
  415.                  
  416.         if (!grad->has_alpha) {
  417. #ifdef FULL_AA
  418.         if (start == end) {
  419.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  420.             if ((unsigned long)dist2 >= 65536) {
  421.                 r = 255;                    
  422.             } else {                        
  423.                 r= SQRT[dist2];    
  424.             }
  425.             mix_alpha(point, ramp[r], start_alpha + end_alpha - 255);
  426.         } else {
  427.             if (start_alpha < 255) {
  428.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  429.             if ((unsigned long)dist2 >= 65536) {
  430.                 r = 255;                    
  431.             } else {                        
  432.                 r= SQRT[dist2];    
  433.             }
  434.             mix_alpha(point, ramp[r], start_alpha);
  435.             point+=BPP;
  436.             X += dx;                        
  437.             Y += dy;                        
  438.             n--;
  439.             }
  440. #endif /* FULL_AA */
  441.             while (n>0) {                    
  442.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  443.             if ((unsigned long)dist2 >= 65536) {
  444.                 r = 255;                    
  445.             } else {                        
  446.                 r= SQRT[dist2];    
  447.             }
  448.             *point++ = ramp[r].blue;
  449.             *point++ = ramp[r].green;
  450.             *point++ = ramp[r].red;
  451.             X += dx;                        
  452.             Y += dy;                        
  453.             n--;
  454.             }        
  455. #ifdef FULL_AA
  456.             if (end_alpha > 0) {
  457.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  458.             if ((unsigned long)dist2 >= 65536) {
  459.                 r = 255;                    
  460.             } else {                        
  461.                 r= SQRT[dist2];    
  462.             }
  463.             mix_alpha(point, ramp[r], end_alpha);
  464.             }
  465.         }
  466. #endif /* FULL_AA */
  467.  
  468.         } else {
  469.             while (n--) {                    
  470.         dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  471.         if ((unsigned long)dist2 >= 65536) {
  472.                     r = 255;                    
  473.         } else {                        
  474.                     r= SQRT[dist2];    
  475.         }
  476.                 cp = &ramp[r];
  477.         mix_alpha(point, *cp, cp->alpha);
  478.         point+=BPP;
  479.         X += dx;                        
  480.         Y += dy;                        
  481.             }        
  482.         }
  483. }
  484.  
  485. void
  486. GraphicDevice24::drawLine(long x1, long y1, long x2, long y2, long width)
  487. {
  488.     int n,adr,dx,dy,sx;
  489.     Color color;
  490.     register int a;
  491.     register TYPE *pp;
  492.     int alpha;
  493.  
  494.     x1 = (x1) >> FRAC_BITS;
  495.     y1 = (y1) >> FRAC_BITS;
  496.     x2 = (x2) >> FRAC_BITS;
  497.     y2 = (y2) >> FRAC_BITS;
  498.     
  499.     if (y1 > y2 || (y1 == y2 && x1 > x2)) {
  500.         long tmp;
  501.  
  502.         tmp=x1;
  503.         x1=x2;
  504.         x2=tmp;
  505.  
  506.         tmp=y1;
  507.         y1=y2;
  508.         y2=tmp;
  509.     }
  510.  
  511.     if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return;
  512.     if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return;
  513.     if (x1 == x2 && y1 == y2) return;    // Bad !!!
  514.  
  515.     if (y1 < clip_rect.ymin && y1 != y2) {
  516.     x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1);
  517.     y1 = clip_rect.ymin;
  518.     }
  519.  
  520.     if (y2 > clip_rect.ymax && y1 != y2) {
  521.     x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1);
  522.     y2 = clip_rect.ymax;
  523.     }
  524.  
  525.     if (x1 < x2) {
  526.         if (x1 < clip_rect.xmin && x1 != x2) {
  527.         y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1);
  528.         x1 = clip_rect.xmin;
  529.         }
  530.  
  531.         if (x2 > clip_rect.xmax && x1 != x2) {
  532.         y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1);
  533.         x2 = clip_rect.xmax;
  534.         }
  535.     }
  536.  
  537.     if (x1 > x2) {
  538.         if (x2 < clip_rect.xmin && x2 != x1) {
  539.         y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2);
  540.         x2 = clip_rect.xmin;
  541.         }
  542.  
  543.         if (x1 > clip_rect.xmax && x2 != x1) {
  544.         y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2);
  545.         x1 = clip_rect.xmax;
  546.         }
  547.     }
  548.  
  549.     // Check again
  550.     if (x1 == x2 && y1 == y2) return;
  551.     if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return;
  552.     if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return;
  553.     if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return;
  554.     if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return;
  555.  
  556.     sx=bpl >> 1;
  557.     adr=(y1 * sx + x1);
  558.     pp = (TYPE *)canvasBuffer + adr;
  559.     
  560.     dx = x2 - x1;
  561.     dy = y2 - y1;
  562.  
  563.     color = foregroundColor;
  564.     alpha = foregroundColor.alpha;
  565.  
  566.     if (alpha == ALPHA_OPAQUE) {
  567.  
  568. #define PUTPIXEL()                 \
  569.   {                        \
  570.       *pp++=color.red;                        \
  571.       *pp++=color.green;                    \
  572.       *pp++=color.blue;                        \
  573.   }
  574.  
  575. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  576.     n=dx;\
  577.     a=2*dy-dx;\
  578.     dy=2*dy;\
  579.     dx=2*dx-dy;\
  580.      do {\
  581.       PUTPIXEL();\
  582.             if (a>0) { pp+=(inc_1); a-=dx; }\
  583.             else { pp+=(inc_2); a+=dy; }\
  584.      } while (--n >= 0);
  585.  
  586. /* fin macro */
  587.  
  588.   if (dx == 0 && dy == 0) {
  589.     PUTPIXEL();
  590.   } else if (dx > 0) {
  591.     if (dx >= dy) {
  592.       DRAWLINE(dx, dy, sx + 1, 1);
  593.     } else {
  594.       DRAWLINE(dy, dx, sx + 1, sx);
  595.     }
  596.   } else {
  597.     dx = -dx;
  598.     if (dx >= dy) {
  599.       DRAWLINE(dx, dy, sx - 1, -1);
  600.     } else {
  601.       DRAWLINE(dy, dx, sx - 1, sx);
  602.     }
  603.   }
  604.  
  605.  
  606. #undef DRAWLINE
  607. #undef PUTPIXEL
  608.     } else {
  609. #define PUTPIXEL()                 \
  610.   {                        \
  611.       mix_alpha(pp,color,alpha);            \
  612.   }
  613.  
  614. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  615.     n=dx;\
  616.     a=2*dy-dx;\
  617.     dy=2*dy;\
  618.     dx=2*dx-dy;\
  619.      do {\
  620.       PUTPIXEL();\
  621.         if (a>0) { pp+=(inc_1*BPP); a-=dx; }\
  622.         else { pp+=(inc_2*BPP); a+=dy; }\
  623.      } while (--n >= 0);
  624.  
  625. /* fin macro */
  626.  
  627.   if (dx == 0 && dy == 0) {
  628.     PUTPIXEL();
  629.   } else if (dx > 0) {
  630.     if (dx >= dy) {
  631.       DRAWLINE(dx, dy, sx + 1, 1);
  632.     } else {
  633.       DRAWLINE(dy, dx, sx + 1, sx);
  634.     }
  635.   } else {
  636.     dx = -dx;
  637.     if (dx >= dy) {
  638.       DRAWLINE(dx, dy, sx - 1, -1);
  639.     } else {
  640.       DRAWLINE(dy, dx, sx - 1, sx);
  641.     }
  642.   }
  643.  
  644.  
  645. #undef DRAWLINE
  646. #undef PUTPIXEL
  647.     }
  648. }
  649.